#include "myapp.h"
#include "ex_dialog.h"

DECLARE_APP(MyApp);

BEGIN_EVENT_TABLE(ExpenseDialog, wxDialog)
	EVT_BUTTON(expense_ok,ExpenseDialog::ed_OkBtn_clicked)
	EVT_BUTTON(expense_can,ExpenseDialog::ed_CanBtn_clicked)
	EVT_BUTTON(expense_add,ExpenseDialog::ed_AddExpense_clicked)
	EVT_BUTTON(expense_mod,ExpenseDialog::ed_ModExpense_clicked)
	EVT_BUTTON(expense_del,ExpenseDialog::ed_DelExpense_clicked)
	EVT_LISTBOX(expense_list,ExpenseDialog::ed_ExpenseList_selected)
	EVT_RADIOBOX(expense_iobox,ExpenseDialog::ed_IOtype_selected)
	EVT_BUTTON(expense_setitems,ExpenseDialog::ed_SettingItemsBtn_clicked)
END_EVENT_TABLE() 

//---------------------------------------------------------------
// ExpenseDialog constructor
//---------------------------------------------------------------
ExpenseDialog::ExpenseDialog(wxWindow *parent)
:wxDialog(parent, wxID_ANY, _("Setting of Expense and Items"), wxDefaultPosition, wxDefaultSize)
{
	SetClientSize(wxSize(420,350));

	wxString incometype_items[] = {
		_("income"),_("expenditure")
	};

	ed_ExpenseList = new wxListBox(this,expense_list,wxDefaultPosition,wxSize(160,240),0,NULL);
	ed_AddExpense = new wxButton(this, expense_add, _("Add"), wxPoint(-1,-1),wxSize(120,-1));
	ed_ModExpense = new wxButton(this, expense_mod, _("Modify"), wxPoint(-1,-1),wxSize(120,-1));
	ed_DelExpense = new wxButton(this, expense_del, _("Remove"), wxPoint(-1,-1),wxSize(120,-1));
	
	ed_ExpenseInfo = new wxStaticBox(this, wxID_ANY, _("Infomation of expense"));
	wxStaticText *label1 = new wxStaticText(this,wxID_ANY,_("Expense name:"));
	ed_InputExpenseName = new wxTextCtrl(this, wxID_ANY, _T(""),wxDefaultPosition,wxSize(120,-1));
	ed_SettingItemsBtn = new wxButton(this, expense_setitems, _("manage items"), wxPoint(-1,-1),wxSize(120,-1));
	
	ed_ExpenseImage = new wxBitmapComboBox(this,wxID_ANY,_T(""),wxDefaultPosition,wxSize(180,-1),0,NULL,wxCB_READONLY);
	ed_IOtype = new wxRadioBox(this,expense_iobox,_("type of transaction"),wxDefaultPosition,wxSize(160,-1),2,incometype_items,2,wxRA_SPECIFY_ROWS);

	ed_OkBtn = new wxButton(this, expense_ok, _T("OK"), wxPoint(-1,-1),wxSize(85,-1));
	ed_CanBtn = new wxButton(this, expense_can, _("Cancel"), wxPoint(-1,-1),wxSize(85,-1));
	
	it_dialog = new ItemsDialog(this);
	
	wxBoxSizer *bsizer1 = new wxBoxSizer(wxVERTICAL);
		wxBoxSizer *bsizer2 = new wxBoxSizer(wxHORIZONTAL);
			wxBoxSizer *bsizer5 = new wxBoxSizer(wxVERTICAL);
			bsizer5->Add(ed_IOtype,0,wxTOP|wxLEFT,0);
			bsizer5->Add(ed_ExpenseList,1,wxTOP|wxLEFT|wxEXPAND,0);
		bsizer2->Add(bsizer5,0,wxTOP|wxLEFT,0);
			wxBoxSizer *bsizer3 = new wxBoxSizer(wxVERTICAL);
				wxStaticBoxSizer *sbsizer = new wxStaticBoxSizer(ed_ExpenseInfo,wxVERTICAL);
				sbsizer->Add(ed_AddExpense,0,wxTOP|wxLEFT,0);
				sbsizer->Add(ed_ModExpense,0,wxTOP|wxLEFT,0);
				sbsizer->Add(ed_DelExpense,0,wxTOP|wxLEFT,0);
				sbsizer->Add(label1,0,wxTOP,15);
				sbsizer->Add(ed_InputExpenseName,0,wxTOP|wxLEFT,0);
				sbsizer->Add(ed_SettingItemsBtn,0,wxTOP,5);
				sbsizer->Add(ed_ExpenseImage,0,wxTOP,5);
			//bsizer3->AddSpacer(60);
			bsizer3->Add(sbsizer,0,wxTOP|wxLEFT,0);
		bsizer2->Add(bsizer3,0,wxTOP|wxLEFT,5);
	bsizer1->Add(bsizer2,0,wxBOTTOM,5);
		wxBoxSizer *bsizer4 = new wxBoxSizer(wxHORIZONTAL);
		bsizer4->Add(ed_OkBtn,0,wxTOP|wxLEFT,0);
		bsizer4->Add(ed_CanBtn,0,wxLEFT,5);
	bsizer1->Add(bsizer4,0,wxRIGHT|wxALIGN_RIGHT,10);
	this->SetSizer(bsizer1);
	this->Layout();
	
	in_expense = 0;
	out_expense = 0;
}
//---------------------------------------------------------------
// ExpenseDialog destructor
//---------------------------------------------------------------
ExpenseDialog::~ExpenseDialog(void)
{
	it_dialog->Close();
}
//---------------------------------------------------------------
// OkBtn click event
//---------------------------------------------------------------
void ExpenseDialog::ed_OkBtn_clicked(wxCommandEvent &event)
{
	this->EndModal(expense_ok);
	this->Hide();
}
//---------------------------------------------------------------
// CanBtn click event
//---------------------------------------------------------------
void ExpenseDialog::ed_CanBtn_clicked(wxCommandEvent &event)
{
	this->EndModal(expense_can);
	this->Hide();
}
//---------------------------------------------------------------
// AddExpense click event
//---------------------------------------------------------------
void ExpenseDialog::ed_AddExpense_clicked(wxCommandEvent &event)
{
	if (ed_InputExpenseName->IsEmpty()) {
		wxMessageBox(_("You don't to input the Expense name."),APPTITLE,
			wxOK|wxICON_EXCLAMATION,this);
		return;
	}
	DB_expense db;
	db.SetFlag(add_mt);
	maxexpenseId++;
	db.SetId(maxexpenseId);
	db.SetIO((InoutType)ed_IOtype->GetSelection());

	db.SetImage(ed_ExpenseImage->GetSelection()-1);
	db.SetName(ed_InputExpenseName->GetValue());
	db.SetAccount(false);
	dbexpense.push_back(db);
	dbexpenseId.push_back(db.GetId());
	ed_ExpenseList->Append(ed_InputExpenseName->GetValue());
	ed_InputExpenseName->Clear();
	maxitemsId.push_back(0);
}
//---------------------------------------------------------------
// ModExpense click event
//---------------------------------------------------------------
void ExpenseDialog::ed_ModExpense_clicked(wxCommandEvent &event)
{
	if (ed_InputExpenseName->IsEmpty()) {
		wxMessageBox(_("You don't to input the Expense name."),APPTITLE,
			wxOK|wxICON_EXCLAMATION,this);
		return;
	}
	int sel = ed_ExpenseList->GetSelection();
	int selectid = dbexpenseId.at(sel) - 1;
	if (dbexpense.at(selectid).GetFlag() != add_mt) {
		dbexpense.at(selectid).SetFlag(mod_mt);
	}
	//db.SetId(dbexpense.size());
	dbexpense.at(selectid).SetImage(ed_ExpenseImage->GetSelection()-1);
	dbexpense.at(selectid).SetName(ed_InputExpenseName->GetValue());
	ed_ExpenseList->SetString(sel,ed_InputExpenseName->GetValue());
}
//---------------------------------------------------------------
// DelExpense click event
//---------------------------------------------------------------
void ExpenseDialog::ed_DelExpense_clicked(wxCommandEvent &event)
{
	int sel = ed_ExpenseList->GetSelection();
	if ((sel >= 0) && (sel <= 1)) {
		wxMessageBox(StrF(_("%s can not remove."),ed_InputExpenseName->GetValue().c_str()),APPTITLE,wxOK|wxICON_EXCLAMATION,this);
		return;
	}
	if (dbexpense.at(dbexpenseId.at(sel) - 1).GetFlag() == add_mt) {
		dbexpense.erase(dbexpense.begin()+sel);
		maxitemsId.pop_back();
	}else{
		dbexpense.at(dbexpenseId.at(sel) - 1).SetFlag(del_mt);
	}
	ed_ExpenseList->Delete(sel);
	ed_InputExpenseName->Clear();
}
//---------------------------------------------------------------
// ExpenseList item select event
//---------------------------------------------------------------
void ExpenseDialog::ed_ExpenseList_selected(wxCommandEvent &event)
{
	int sel = event.GetSelection();
	ed_InputExpenseName->SetValue(event.GetString());
	ed_ExpenseImage->SetSelection(dbexpense.at(dbexpenseId.at(sel)-1).GetImage()+1);
	return;
}
//---------------------------------------------------------------
// Input-Output type list select event
//---------------------------------------------------------------
void ExpenseDialog::ed_IOtype_selected(wxCommandEvent &event)
{
	int sel = event.GetSelection();
	if (sel >= 0) {
		ShowExpense((InoutType)sel);
	}
}
//---------------------------------------------------------------
// SettingItemsBtn click event
//---------------------------------------------------------------
void ExpenseDialog::ed_SettingItemsBtn_clicked(wxCommandEvent &event)
{
	int sel = ed_ExpenseList->GetSelection();
	if ((sel >= 0) && (sel <= 1)) {
		wxMessageBox(StrF(_("%s can not edit items."),ed_InputExpenseName->GetValue().c_str()),APPTITLE,wxOK|wxICON_EXCLAMATION,this);
		return;
	}
	if (sel < 0) return;
	it_dialog->BindData_Items(dbexpenseId.at(sel),&dbitems,maxitemsId.at(dbexpenseId.at(sel)-1));
	it_dialog->BindData_Icon();
	it_dialog->CentreOnParent();
	if (it_dialog->ShowModal() == items_ok) {
		maxitemsId.at(dbexpenseId.at(sel)-1) = it_dialog->GetUpdatedItemsId();
	}
}
//---------------------------------------------------------------
// Bind current data and DB(Expense)
//---------------------------------------------------------------
void ExpenseDialog::BindData_Expense(wxSQLite3ResultSet &table)
{
	dbexpense.clear();
	maxitemsId.clear();
	in_expense = 0;
	out_expense = 0;
	while (table.NextRow()) {
		DB_expense db;
		db.SetFlag(none_mt);
		db.SetId(table.GetInt(0));
		db.SetIO((InoutType)table.GetInt(1));
		if (db.GetIO() == in_it) {
			in_expense++;
		}else{
			out_expense++;
		}
		db.SetImage(table.GetInt(2));
		db.SetName(table.GetString(3));
		db.SetAccount(table.GetInt(4) == 1 ? true : false);
		dbexpense.push_back(db);
	}
	//get max count of expense id
	maxexpenseId = wxGetApp().SQLDB().ExecuteScalar(
		_T("select ifnull(max(ex_id),0) from db_expense;"));
	for (int i = 1; i <= maxexpenseId; i++) {
		maxitemsId.push_back(wxGetApp().AppDB.GetLastIdOfItems(i));
	}
	//maxitemsId = wxGetApp().SQLDB().ExecuteScalar(
	//	_T("select ifnull(max(it_id),0) from db_items;"));
	ShowExpense((InoutType)ed_IOtype->GetSelection());
}
//---------------------------------------------------------------
// Bind current data and DB(Items of expense)
//---------------------------------------------------------------
void ExpenseDialog::BindData_Items(wxSQLite3ResultSet &table)
{
	dbitems.clear();
	while (table.NextRow()) {
		DB_items db;
		db.SetFlag(none_mt);
		db.SetId(table.GetInt(0));
		db.SetImage(table.GetInt(1));
		db.SetExpense(table.GetInt(2));
		db.SetName(table.GetString(3));
		dbitems.push_back(db);
	}
}
std::vector<DB_expense> ExpenseDialog::GetChangedExpense(modifyType mt)
{
	std::vector<DB_expense> result;
	int i = 0;
	for (i = 0; i < (int)dbexpense.size(); i++) {
		if ((mt == none_mt) && (dbexpense.at(i).GetFlag() != mt)) {
			result.push_back(dbexpense.at(i));
		}else{
			if (dbexpense.at(i).GetFlag() == mt) {
				result.push_back(dbexpense.at(i));
			}
		}
	}
	return result;
}
std::vector<DB_items> ExpenseDialog::GetChangedItems(modifyType mt)
{
	std::vector<DB_items> result;
	int i = 0;
	for (i = 0; i < (int)dbitems.size(); i++) {
		if ((mt == none_mt) && (dbitems.at(i).GetFlag() != mt)) {
			result.push_back(dbitems.at(i));
		}else{
			if (dbitems.at(i).GetFlag() == mt) {
				result.push_back(dbitems.at(i));
			}
		}
	}
	return result;
}
void ExpenseDialog::ShowExpense(InoutType io)
{
	ed_ExpenseList->Deselect(ed_ExpenseList->GetSelection());
	ed_ExpenseList->Clear();
	dbexpenseId.clear();
	int i = 0;
	for (i = 0; i < (int)dbexpense.size(); i++) {
		if (dbexpense.at(i).GetIO() == io) {
			ed_ExpenseList->Append(dbexpense.at(i).GetName());
			dbexpenseId.push_back(dbexpense.at(i).GetId());
		}
	}
}
void ExpenseDialog::BindData_Icon(wxImageList *list)
{
	ed_ExpenseImage->Clear();
	ed_ExpenseImage->Append(_T("None"));
	for (int i = 0; i < (int)list->GetImageCount(); i++) {
		ed_ExpenseImage->Append(StrF(_T("Icon %d"),i+1),list->GetBitmap(i));
	}
	ed_ExpenseImage->SetSelection(0);
}